package com.lhgray.sglhome.presentation.viewModel

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationManager
import android.net.Uri
import android.os.Looper
import androidx.core.app.ActivityCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.freightoa.foundation.viewmodel.BaseState
import com.freightoa.foundation.viewmodel.UiIntent
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.lhgray.sglhome.domain.model.Source
import com.lhgray.sglhome.domain.model.TruckingBean
import com.lhgray.sglhome.domain.usecase.TruckingPostUseCase
import com.lhgray.sglhome.domain.usecase.TruckingUseCase
import com.lhgray.sglhome.presentation.ui.activity.UploadPhotoActivity
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * 卡车的处理逻辑
 */

sealed class TruckState {
    data class Loading(val isLoading: Boolean) : TruckState()
    data class Error(val errorMessage: Int) : TruckState()
    data class Success(val data: TruckingState) : TruckState()
    data class Toast(val toast: String?) : TruckState()
    data object Ide : TruckState()
}

data class TruckingState(
    val truckingBean: TruckingBean? = null,
    val isLoading: Boolean = false,
    val errorMsg: String? = null,
    val toast: String? = ""
) : BaseState


@HiltViewModel
class TruckingViewModel @Inject constructor(
    private val truckingUseCase: TruckingUseCase,
    private val truckingPostUseCase: TruckingPostUseCase
) : ViewModel() {
    private val _truckState: MutableStateFlow<TruckState> = MutableStateFlow(TruckState.Ide)
    private val _truckingBean: MutableStateFlow<TruckingBean?> = MutableStateFlow(null)
    private val _loading: MutableStateFlow<Boolean> = MutableStateFlow(false)
    private val _errorMsg: MutableStateFlow<Throwable?> = MutableStateFlow(null)

    val uiState: StateFlow<TruckingState> = combine(
        _truckingBean, _loading, _errorMsg, _truckState
    ) { truckingBean, loading, errorMsg, truckState ->
        when (truckState) {
            is TruckState.Error -> {
                TruckingState(truckingBean, false, errorMsg?.message)
            }

            is TruckState.Loading -> {
                TruckingState(truckingBean, true, null)
            }

            is TruckState.Success -> {
                TruckingState(truckingBean, false, null)
            }

            is TruckState.Toast -> {
                TruckingState(truckingBean, false, null, truckState.toast)
            }

            TruckState.Ide -> TruckingState()
        }

    }.stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5000),
        initialValue = TruckingState(null, isLoading = false)
    )

    fun getTruckingJob(fileNo: String) {
        if (fileNo.isEmpty()) return
        _truckState.value = TruckState.Loading(true)
        viewModelScope.launch {
            val result = truckingUseCase.invoke(fileNo)
            if (result.isSuccess) {
                _truckingBean.value = result.getOrDefault(TruckingBean())!!
                _truckState.value = TruckState.Success(TruckingState())
            } else {
                val exceptionOrNull = result.exceptionOrNull()
                _errorMsg.value = exceptionOrNull
                _truckState.value = TruckState.Error(0)
            }
        }
    }

    /**
     *1.现权限的方法
     */
    fun postTruckingJob(
        context: Context,
        fileNo: String,
        location: Location?
    ) {
        viewModelScope.launch {
            if (index < 0) {
                _errorMsg.value = RuntimeException("index = -1")
                _truckState.value = TruckState.Error(0)
                return@launch
            }
            _truckingBean.value?.let {
                val listStemStatus = it.list_item_status[index]
                val itemStatus = listStemStatus.copy(
                    lon = location?.longitude,
                    lat = location?.latitude,
                )
                val truckingBean = TruckingBean(
                    it.source,
                    it.list_item_label,
                    mutableListOf(itemStatus)
                )
                _truckState.value = TruckState.Loading(true)
                val result = truckingPostUseCase.invoke(truckingBean)
                if (result.isSuccess) {
                    val resultSuccess = result.getOrNull()
                    _truckState.value = TruckState.Toast(resultSuccess?.message_en ?: "Success")
                    getTruckingJob(fileNo)
                    jumpUpload(context, it.source, location)
                } else {
                    _errorMsg.value = result.exceptionOrNull()
                    _truckState.value = TruckState.Error(0)
                }
                saveTruckingJobIndex(-1)
            }
        }
    }

    private fun jumpUpload(context: Context, source: Source?, location: Location?) {
        source?.let {
            val intent = Intent(context, UploadPhotoActivity::class.java)
            intent.putExtra("source_table", source.source_table)
            intent.putExtra("source_id", source.source_id.toString())
            intent.putExtra("longitude", location?.longitude.toString())
            intent.putExtra("latitude", location?.latitude.toString())
            context.startActivity(intent)
        }

    }

    /**
     * 创建一个方法存储仓库点击的东西
     */

    private var index: Int = -1
    fun saveTruckingJobIndex(index: Int) {
        this.index = index
    }

    private fun isLocationEnabled(context: Context): Boolean {
        val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
    }

    private lateinit var fusedLocationClient: FusedLocationProviderClient
    fun getLastLocation(context: Context, onLocationResult: (Location?) -> Unit) {
        if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            _errorMsg.value = RuntimeException("Lack of location permission")
            _truckState.value = TruckState.Error(0)
            return
        }
        _truckState.value = TruckState.Loading(true)
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
        requestLocationUpdates(context, null)
        fusedLocationClient.lastLocation
            .addOnSuccessListener { location: Location? ->
                if (location != null) {
                    onLocationResult(location)
                } else {
                    requestLocationUpdates(context, onLocationResult)
                }
            }
            .addOnFailureListener { e ->
                println(e)
            }
    }

    private fun requestLocationUpdates(context: Context, onLocationResult: ((Location?) -> Unit)?) {
        if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }
        val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 10000)
            .setMinUpdateIntervalMillis(5000)
            .build()

        val locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                super.onLocationResult(locationResult)
                locationResult.lastLocation.let {
                    if (onLocationResult!=null){
                        onLocationResult(it)
                    }
                }
                fusedLocationClient.removeLocationUpdates(this)
            }
        }
        fusedLocationClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.getMainLooper()
        )
    }

    sealed interface TruckingIntent : UiIntent {
        data class Trucking(val list: MutableList<Uri>) : TruckingIntent
    }

}